/*
	stair.cpp

	Author: Chris Haag
	Description:

		Defines body of a single stair.
*/

#include "stair.h"
#include <memory.h>

CStair::CStair(float x, float y, float z, float w, float l,
			   eTextures texture) :
CPSystem()
{
	m_Type = eStair;

	// Build physics
	m_vCenter.x = x;
	m_vCenter.y = y;
	m_vCenter.z = z;
	m_Mass = 100000; // I really want this to be infinity
	m_OneOverMass = 1.0f / m_Mass;

	m_matInvI.ZeroMatrix();
	m_matInvI(0,0) = 3 / (m_Mass * (1*1+l*l));
	m_matInvI(1,1) = 3 / (m_Mass * (w*w+l*l));
	m_matInvI(2,2) = 3 / (m_Mass * (w*w+1*1));

	m_vStatic = new _VERTEX[6];
	m_v = new _VERTEX[6];	
	m_f = new _FACE[2];
	m_tex = new _TEXCOORD[6];

	AddFlatFace(y, x-w, z-l, x+w, z+l);

	m_tex[0].x = 0; m_tex[0].y = 0;
	m_tex[1].x = 0; m_tex[1].y = 1;
	m_tex[2].x = 1; m_tex[2].y = 0;
	m_tex[3].x = 1; m_tex[3].y = 1;
	m_tex[4].x = 1; m_tex[4].y = 0;
	m_tex[5].x = 1; m_tex[5].y = 1;

	m_texture = texture;
}

CStair::~CStair()
{
}

void CStair::AddFlatFace(float y, float x1, float z1,
	float x2, float z2)
{
	_VERTEX* v;
	_VERTEX* q;
	_FACE* f;

	// Don't let your programming teacher know
	// that I'm not checking to see if the pointer
	// is ever out of bounds...

	// These first four are for the up-facing stair
	q = v = &m_vStatic[m_nVertices++];
	v->x = x1; v->y = y; v->z = z1;

	v = &m_vStatic[m_nVertices++];
	v->x = x1; v->y = y; v->z = z2;

	v = &m_vStatic[m_nVertices++];
	v->x = x2; v->y = y; v->z = z2;

	v = &m_vStatic[m_nVertices++];
	v->x = x2; v->y = y; v->z = z1;

	// These last two are for the front-facing part
	// of the stair
	v = &m_vStatic[m_nVertices++];
	v->x = x1; v->y = y - STAIR_HEIGHT; v->z = z1;

	v = &m_vStatic[m_nVertices++];
	v->x = x2; v->y = y - STAIR_HEIGHT; v->z = z1;
	//

	memcpy(m_v, m_vStatic, sizeof(_VERTEX)*m_nVertices);

	// Top face
	f = &m_f[m_nFaces++];
	f->pIndices = new unsigned short[4];
	f->nIndices = 4;
	for (int i=0; i < 4; i++)
		f->pIndices[i] = i;
	CalculateNormal(q, q+1, q+2, f->vStaticNorm);
	f->vNorm = f->vStaticNorm;

	// Front face
	f = &m_f[m_nFaces++];
	f->pIndices = new unsigned short[4];
	f->nIndices = 4;
	f->pIndices[0] = 0;
	f->pIndices[1] = 3;
	f->pIndices[2] = 5;
	f->pIndices[3] = 4;
	CalculateNormal(q, q+3, q+5, f->vStaticNorm);
	f->vNorm = f->vStaticNorm;
}

void CStair::Draw()
{
	_FACE* f = m_f;
	float fAmb[4] = { 0,0,0,1 };
	float fDiff[4] = { 1,1,1,1 };

	glMaterialfv(GL_FRONT, GL_AMBIENT, fAmb);
	glMaterialfv(GL_FRONT, GL_DIFFUSE, fDiff);

	glVertexPointer(3, GL_FLOAT, sizeof(_VERTEX), m_v);
	glBindTexture ( GL_TEXTURE_2D, g_texture_id[m_texture] );
	glTexCoordPointer(2, GL_FLOAT, sizeof(_TEXCOORD), m_tex);

	for (int i=0; i < m_nFaces; i++, f++)
	{
		glNormal3f(f->vNorm.a, f->vNorm.b, f->vNorm.c);
		glDrawElements(GL_TRIANGLE_FAN, f->nIndices, GL_UNSIGNED_SHORT, f->pIndices);
	}
	
	if (m_v[0].y != 0)
	{
		// This code actually draws the side of the stair
		// facing the camera. It has to be done here
		// because it's not really part of our physical
		// world.

		glNormal3f(1,0,0);
		glBegin(GL_TRIANGLE_FAN);
		glTexCoord2f(0,0); glVertex3f(m_v[2].x, 0, m_v[0].z);
		glTexCoord2f(0,1); glVertex3f(m_v[2].x, m_v[0].y, m_v[0].z);
		glTexCoord2f(1,0); glVertex3f(m_v[2].x, m_v[0].y, m_v[1].z);
		glTexCoord2f(1,1); glVertex3f(m_v[2].x, 0, m_v[1].z);
		glEnd();
	}
}

void CStair::Action(CPSystem* p)
{
}

void CStair::Reaction(float t)
{
}

void CStair::Influence(CPSystem* p)
{
	// Just a little shortcut; no point
	// in collision detection with anything
	// not a cube
	if (p->GetType() != eCube)
		return;

	int i = 0;
	while (CollisionDetect(this, p) && i < MAX_ALLOWABLE_COLLISIONS_PER_TRY)
		i++;
}

void CStair::DrawShadow(GLfloat shadowMat[4][4])
{
	if (m_texture == texFloor || m_v[0].y == 0)
		return;

    glColor4f(0.0, 0.0, 0.0, 0.5);

	glNormal3f(1,0,0);
	glBegin(GL_TRIANGLE_FAN);
	glTexCoord2f(0,0); glVertex3f(m_v[2].x, 0, m_v[0].z);
	glTexCoord2f(0,1); glVertex3f(m_v[2].x, m_v[0].y, m_v[0].z);
	glTexCoord2f(1,0); glVertex3f(m_v[2].x, m_v[0].y, m_v[1].z);
	glTexCoord2f(1,1); glVertex3f(m_v[2].x, 0, m_v[1].z);
	glEnd();

	glNormal3f(0,0,-1);
	glBegin(GL_TRIANGLE_FAN);
	glTexCoord2f(0,0); glVertex3f(m_v[1].x, m_v[0].y, m_v[0].z);
	glTexCoord2f(0,1); glVertex3f(m_v[2].x, m_v[0].y, m_v[0].z);
	glTexCoord2f(1,0); glVertex3f(m_v[2].x, m_v[0].y - STAIR_HEIGHT, m_v[0].z);
	glTexCoord2f(1,1); glVertex3f(m_v[1].x, m_v[0].y - STAIR_HEIGHT, m_v[0].z);
	glEnd();
}
